package com.tianji.learning.service.impl;

import cn.hutool.db.DbRuntimeException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.CollUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionDetailVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author yb0os1
 * @since 2024-12-21
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion> implements IInteractionQuestionService {
    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;

    /**
     * 新增互动问题
     *
     * @param questionDTO 互动问题表单信息
     */
    @Override
    @Transactional
    public void addQuestion(QuestionFormDTO questionDTO) {
        //1、获取当前用户
        Long userId = UserContext.getUser();

        //2、数据dto转换为po
        InteractionQuestion interactionQuestion = BeanUtils.copyBean(questionDTO, InteractionQuestion.class);

        //3、补充数据
        interactionQuestion.setUserId(userId);

        //4、保存数据
        boolean isSuccess = save(interactionQuestion);
        if (!isSuccess) {
            throw new DbRuntimeException("新增互动问题失败");
        }
    }

    /**
     * 编辑互动问题
     *
     * @param questionDTO
     */
    @Override
    @Transactional
    public void editQuestion(Long id, QuestionFormDTO questionDTO) {
        //1、检验参数
        if (StringUtils.isBlank(questionDTO.getTitle())
                || StringUtils.isBlank(questionDTO.getDescription())
                || questionDTO.getAnonymity() == null) {
            throw new BizIllegalException("参数错误");
        }

        //2、根据问题id获取问题信息
        InteractionQuestion question = getById(id);
        if (question == null) {
            throw new BizIllegalException("问题不存在");
        }

        //3、校验用户
        if (!question.getUserId().equals(UserContext.getUser())) {
            throw new BizIllegalException("没有权限编辑该问题");
        }

        //4、进行更新
        boolean success = lambdaUpdate()
                .set(InteractionQuestion::getTitle, questionDTO.getTitle())
                .set(InteractionQuestion::getDescription, questionDTO.getDescription())
                .set(InteractionQuestion::getAnonymity, questionDTO.getAnonymity())
                .eq(InteractionQuestion::getId, id)
                .update();
        if (!success) {
            throw new DbRuntimeException("编辑互动问题失败");
        }

    }

    /**
     * 用户端分页查询
     *
     * @param page 分页参数
     * @return
     */
    @Override
    public PageDTO<QuestionVO> queryUserQuestionPage(QuestionPageQuery page) {
        //1、参数校验 课程id必须存在 可以不查找具体的小节
        if (page.getCourseId() == null) {
            throw new BizIllegalException("参数错误");
        }
        //2、进行分页查询设置
        //获取当前用户 因为我们要确定是否只差自己的提问
        //因为description是很大的 我们查询的时候不想查询出来
        Long userId = UserContext.getUser();
        Page<InteractionQuestion> pageRes = lambdaQuery()
                //返回false就代表不需要
                .select(InteractionQuestion.class, tableFieldInfo -> !tableFieldInfo.getProperty().equals("description"))
                .eq(page.getOnlyMine(), InteractionQuestion::getUserId, userId)
                .eq(InteractionQuestion::getCourseId, page.getCourseId())
                .eq(page.getSectionId() != null, InteractionQuestion::getSectionId, page.getSectionId())
                .eq(InteractionQuestion::getHidden, false)
                .page(page.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageRes.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(pageRes);
        }
        //3、需要查询用户信息和最近一次回答者信息
        //封装一下他们两者的ids集合
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>();
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {//只查询非匿名的问题
                userIds.add(record.getUserId());
            }
            latestAnswerIds.add(record.getLatestAnswerId());
        }
        //4、根据id查询最近一次回答
        Map<Long, InteractionReply> replyMap = new HashMap<>();
        if (CollUtils.isNotEmpty(latestAnswerIds)) {
            List<InteractionReply> replyList = replyMapper.queryByAnswerIds(latestAnswerIds);
            //reply的id对应一个回复的内容
            replyMap = replyList.stream().collect(Collectors.toMap(InteractionReply::getId, r -> r));
            //将回答者的id加入userIds里面
            for (InteractionReply reply : replyList) {
                replyMap.put(reply.getId(), reply);
                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId());
                }
            }
        }

        //5、根据userIds批量查询用户的信息
        Map<Long, UserDTO> userMap = new HashMap<>();
        if (CollUtils.isNotEmpty(userIds)) {
            List<UserDTO> userList = userClient.queryUserByIds(userIds);
            userMap = userList.stream().collect(Collectors.toMap(UserDTO::getId, u -> u));
        }

        //6、封装VO
        List<QuestionVO> list = new ArrayList<>();
        for (InteractionQuestion record : records) {
            QuestionVO vo = BeanUtils.toBean(record, QuestionVO.class);
            if (!record.getAnonymity()) {
                //非匿名 需要补充提问者昵称 头像
                UserDTO user = userMap.get(record.getUserId());
                vo.setUserIcon(user.getIcon());
                vo.setUserName(user.getName());
                log.info("vo的id{}，user的id{}", vo.getUserId(), user.getId());
            }
            //最新回答的信息和回答者的昵称
            InteractionReply reply = replyMap.get(record.getLatestAnswerId());
            if (reply != null) {
                vo.setLatestReplyContent(reply.getContent());
                if (!reply.getAnonymity()) {
                    vo.setLatestReplyUser(userMap.get(reply.getUserId()).getName());
                }
            }
            list.add(vo);
        }
        return PageDTO.of(pageRes, list);
    }

    /**
     * 在课程详情页用户点击某个互动问题后，会进入问答详情页面，查看问题详细信息
     *
     * @param id
     * @return
     */
    @Override
    public QuestionDetailVO getQuestionDetail(Long id) {
        //1、先查找提出问题的表 补充字段
        InteractionQuestion question = getById(id);
        if (question == null || question.getHidden()) {
            return null;
        }

        //2、创建问题vo
        QuestionDetailVO vo = BeanUtils.toBean(question, QuestionDetailVO.class);
        //3、如果不是匿名的话 我们返回的数据要包含提问者的昵称 头像
        if (!question.getAnonymity()) {
            UserDTO user = userClient.queryUserById(question.getUserId());
            if (user != null) {
                vo.setUserIcon(user.getIcon());
                vo.setUserName(user.getName());
            }
        }
        return vo;
    }

    /**
     * 删除我的问题
     *
     * @param id
     */
    @Transactional
    @Override
    public void deleteMyQuestion(Long id) {
        if (id == null) {
            throw new BizIllegalException("参数错误");
        }
        //1、根据 id userid 查找问题
        Long userId = UserContext.getUser();
        InteractionQuestion question = lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .eq(InteractionQuestion::getUserId, userId)
                .one();
        if (question == null) {
            throw new BizIllegalException("该问题不存在或该问题不是当前用户所提出的");
        }
        //2、判断是否存在回答
        List<InteractionReply> interactionReplies = replyMapper.selectList(
                new LambdaQueryWrapper<InteractionReply>()
                        .eq(InteractionReply::getQuestionId, id));
        if (CollUtils.isNotEmpty(interactionReplies)) {
            //2.1 存在回答要同时删除回答
            List<Long> collect = interactionReplies.stream().map(InteractionReply::getId).collect(Collectors.toList());
            int deleted = replyMapper.deleteBatchIds(collect);
            if (deleted<=0){
                throw new DbRuntimeException("问题的回答删除失败");
            }
        }
        //2.2 不存在结束
        //3、删除问题表中的数据
        boolean isSuccess = removeById(id);
        if (!isSuccess){
            throw new DbRuntimeException("互动问题删除失败");
        }
    }
}
